﻿using System;

namespace BaseApplicationNamespace
{
    /// <summary>
    /// 操作エラーを表します。
    /// </summary>
    /// <remarks>
    /// <para>
    /// <see cref="OperationScript&lt;TOutputs, TErrors&gt;"/> クラスの派生クラス毎に、対となる <see cref="OperationErrors"/> 派生クラスを定義します。
    /// 保守性の観点から、操作スクリプトにエラーが無い場合でも必ず用意します。
    /// </para>
    /// <para>
    /// <see cref="OperationScript&lt;TOutputs, TErrors&gt;"/> クラスの <see cref="OperationScript&lt;TOutputs, TErrors&gt;.Execute()"/> メソッドが失敗した場合、
    /// <see cref="OperationScript&lt;TOutputs, TErrors&gt;.Error"/> イベントが発生します。
    /// エラーは <see cref="ErrorEventArgs&lt;TOutputs&gt;"/> の <see cref="ErrorEventArgs&lt;TOutput&gt;.Errors"/> プロパティから取得できます。
    /// エラーは列挙型ではなく <see cref="OperationErrors"/> クラスの派生クラスとして表されます。
    /// </para>
    /// <para>
    /// 列挙型で表現されるエラーを処理する場合、通常は switch 文の case 文にて各エラーに該当する処理を記述します。
    /// その後、新たな列挙値が追加された場合には対応する case 文を追加する必要があります。
    /// しかし、対応する case 文の追加が漏れていてもコンパイルエラーは検出されません。
    /// </para>
    /// <para>
    /// <see cref="OperationErrors"/> クラスは制御の反転 (Inversion of Control) によりこの問題を解消します。
    /// <see cref="OperationErrors"/> クラスで表現されるエラーは、switch 文では処理できません。
    /// 代わりに、<see cref="IOperationErrorsHandler"/> インターフェイスから派生するエラーハンドラ インターフェイスを実装することでエラーハンドラを定義します。
    /// エラーハンドラ インターフェイスには、各エラーに対応するハンドラメソッドが定義されていて、
    /// エラーハンドラを <see cref="OperationErrors.HandledBy(IOperationErrorsHandler)"/> メソッドの引数として渡すことで、該当するハンドラメソッドが呼び出されます。
    /// エラーが追加された場合インターフェイスへのメソッドの追加が生じるため、
    /// 追加されたメソッドの実装が漏れていればコンパイルエラーが検出されます。
    /// </para>
    /// <para>
    /// 全てのエラーハンドラメソッドで同じ処理を行うエラーハンドラを用意する場合、
    /// <see cref="ErrorsHandlerCreator&lt;THandler&gt;"/> クラスを使用することで、エラーハンドラを動的に生成することができます。
    /// これにより、エラーハンドラインターフェイスの実装クラスの定義を省略することができます。
    /// </para>
    /// <para>
    /// <see cref="OperationErrors"/> クラスを派生させるには、専用の T4 Text Template である Errors.tt を使用します。
    /// これにより、エラークラスとエラーハンドラ インターフェイスが自動生成されます。
    /// Errors.tt を利用するには、ソリューションフォルダ内の Solution Items\My\Templates\Item Templates\Visual C#\Errors.zip を
    /// %USERPROFILE%\My Documents\Visual Studio 2010\Templates\ItemTemplates\Visual C# に配置します。
    /// これにより、[新しい項目の追加] ダイアログから Errors.tt を追加することができるようになります。
    /// </para>
    /// </remarks>
    /// <seealso cref="OperationScript&lt;TOutputs, TErrors&gt;"/>
    /// <seealso cref="IOperationErrorsHandler"/>
    /// <seealso cref="ErrorsHandlerCreator&lt;THandler&gt;"/>
    [Serializable]
    public class OperationErrors
    {
        /// <summary>
        /// 指定したハンドラにエラー処理を委譲します。
        /// </summary>
        /// <param name="handler">エラーを処理するハンドラ。</param>
        /// <exception cref="System.ArgumentNullException">handler が null です。</exception>
        public void HandledBy(IOperationErrorsHandler handler)
        {
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }

        }
    }

    /// <summary>
    /// <see cref="OperationErrors"/> を処理する方法を定義します。
    /// </summary>
    /// <seealso cref="OperationErrors"/>
    public interface IOperationErrorsHandler
    {
    }
}
